// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose: implementation of CXFormsParseSubmitInfo.
//   $Id$


#include "stdafx.h"
#include "submission.h"
#include "parseSubmission.h"
#include "ImplContextualValue.h"
#include "ImplHeader.h"
#include "XFormsParseContextualValue.h"
#include "tags.h"

CMapStringToPtr CXFormsParseSubmitInfo::sm_SerialiseMap;
CMapStringToPtr CXFormsParseSubmitInfo::sm_LocationMap;
CMapStringToPtr CXFormsParseSubmitInfo::sm_ModeMap;
HANDLE CXFormsParseSubmitInfo::sm_hMapsMutex = 0;

CXFormsParseSubmitInfo::CXFormsParseSubmitInfo(CImplSubmitInfo* pImpl)
		: CXFormsParseSingleNodeBinding(pImpl)
{
	if(!sm_hMapsMutex)
		sm_hMapsMutex = CreateMutex(0, FALSE, _T("Local\\XFormsParseSubmitInfoMapsMutex"));

	WaitForSingleObject(sm_hMapsMutex, INFINITE);

	try
	{
		addAttributeCheck(ATTR_METHOD, &pImpl->m_sMethod);
		addAttributeCheck(ATTR_SEPARATE, &pImpl->m_sSeparator);
		addAttributeCheck(ATTR_ACTION, &pImpl->m_sAction);
		addAttributeCheck(ATTR_DOCTYPE_PUBLIC, &pImpl->m_sDoctypePublic);
		addAttributeCheck(ATTR_DOCTYPE_SYSTEM, &pImpl->m_sDoctypeSystem);
		//<xsl:output> attributes
		addAttributeCheck(ATTR_CDATA, &pImpl->m_sCDATASectionElements);
		addAttributeCheck(ATTR_ENCODING, &pImpl->m_sEncoding);
		addAttributeCheck(ATTR_MEDIA, &pImpl->m_sMediaType);
		addAttributeCheck(ATTR_OMITXML, &pImpl->m_sOmitXMLDeclaration);
		addAttributeCheck(ATTR_REPLACE, &pImpl->m_sReplace);
		addAttributeCheck(ATTR_VERSION, &pImpl->m_sVersion);
		addAttributeCheck(ATTR_INSTANCE, &pImpl->m_sReplaceInstance);
		//Boolean values
		addAttributeCheck(ATTR_ALONE, (LPVOID*)&pImpl->m_bStandalone,XFormsParse::parseXSDBoolean);
		addAttributeCheck(ATTR_INDENT, (LPVOID*)&pImpl->m_bIndent,XFormsParse::parseXSDBoolean);
		
		//provisional functionality from a future version of xforms.
		addAttributeCheck(L"instance-error", &pImpl->m_sInstanceError);

		//proprietary formsplayer attribues
		addAttributeCheck(L"real-method",&pImpl->m_sRealMethod);
		addAttributeCheck(L"mediatype",&pImpl->m_sMediaType);
		addAttributeCheck(L"serialise-as", (LPVOID*) &pImpl->m_eSerialisation,&sm_SerialiseMap);
		addAttributeCheck(L"send-in",  (LPVOID*) &pImpl->m_eSerialisedLocation,&sm_LocationMap);
		addAttributeCheck(L"authenticate", (LPVOID*)&pImpl->m_bAuthenticate, XFormsParse::parseXSDBoolean);

		//xforms 1.1 attributes:
		//Overrides of above synonyms:	
			//new "verb" attribute corresponds to fP proprietary "real-method" attribute.
			addAttributeCheck(L"verb",&pImpl->m_sRealMethod);
			//new "resource" attribute takes precedence over synonymous xforms 1.0 "action" attribute
			addAttributeCheck(L"resource",&pImpl->m_sAction);
		
		//attributes moved from above, either proprietary or predicted.
			addAttributeCheck(L"target", &pImpl->m_sTarget);
			addAttributeCheck(ATTR_RELEVANT, (LPVOID*)&pImpl->m_bRelevant,XFormsParse::parseXSDBoolean);
			addAttributeCheck(ATTR_VALIDATE, (LPVOID*)&pImpl->m_bValidate,XFormsParse::parseXSDBoolean);
		
		//new attributes requiring implementation since http://www.w3.org/TR/2006/WD-xforms11-20061103
			//new boolean value to fix "/nodeThatDoesNotExist" fudge.
			addAttributeCheck(L"serialize", (LPVOID*)&pImpl->m_bSerialize,XFormsParse::parseXSDBoolean);
			addAttributeCheck(L"mode", (LPVOID*)&pImpl->m_bSubmitAsynchronously,&sm_ModeMap);
		


		if(sm_SerialiseMap.IsEmpty())
		{
			FillTokenizer();
		}
	}
	catch(...)
	{
	}

	ReleaseMutex(sm_hMapsMutex);
}

void CXFormsParseSubmitInfo::FillTokenizer()
{
	sm_LocationMap.SetAt(_T("url"),(LPVOID)CImplSubmitInfo::ESerialisedLocation::url);
	sm_LocationMap.SetAt(_T("header"),(LPVOID)CImplSubmitInfo::ESerialisedLocation::header);
	sm_LocationMap.SetAt(_T("body"),(LPVOID)CImplSubmitInfo::ESerialisedLocation::body);

	sm_SerialiseMap.SetAt(_T("xml"),(LPVOID)CImplSubmitInfo::ESerialisation::xml);
	sm_SerialiseMap.SetAt(_T("name-value-pair"),(LPVOID)CImplSubmitInfo::ESerialisation::nvpair);
	
	sm_ModeMap.SetAt(_T("asynchronous"),(LPVOID)TRUE);
	sm_ModeMap.SetAt(_T("synchronous"),(LPVOID)FALSE);
}

void CXFormsParseSubmitInfo::CheckElement(IHTMLElement *pElem, BSTR bstrTag, CImpl* pImpl)
{
	if (wcscmp(bstrTag, L"resource") == 0)
	{
		CImplContextualValue * pCV = new CImplContextualValue();
		CComVariant vtTemp;
		pElem->getAttribute(L"value",1,&vtTemp);
		vtTemp.CopyTo(&pCV->m_sValueExpression);
		CImplSubmitInfo * pSubmitInfo = dynamic_cast<CImplSubmitInfo*>(pImpl);
		pSubmitInfo->m_pResourceNameResolver = pCV;

	}
	else if (wcscmp(bstrTag, L"verb") == 0)
	{
		CImplContextualValue * pCV = new CImplContextualValue();
		CComVariant vtTemp;
		pElem->getAttribute(L"value",1,&vtTemp);
		vtTemp.CopyTo(&pCV->m_sValueExpression);
		CImplSubmitInfo * pSubmitInfo = dynamic_cast<CImplSubmitInfo*>(pImpl);
		pSubmitInfo->m_pVerbResolver = pCV;
	}
	else if (wcscmp(bstrTag, L"method") == 0)
	{
		CImplContextualValue * pCV = new CImplContextualValue();
		CComVariant vtTemp;
		pElem->getAttribute(L"value",1,&vtTemp);
		vtTemp.CopyTo(&pCV->m_sValueExpression);
		CImplSubmitInfo * pSubmitInfo = dynamic_cast<CImplSubmitInfo*>(pImpl);
		pSubmitInfo->m_pMethodResolver = pCV;
	}
	else if (wcscmp(bstrTag, L"header") == 0)
	{

		CComQIPtr<IHTMLElement2> pEl2 = pElem;
		CComPtr<IHTMLElementCollection> pColl;
		pEl2->getElementsByTagName(L"name",&pColl);
		long l;
		pColl->get_length(&l);
		if(l > 0)
		{
			CComPtr<IDispatch> pChildDispatch;
			CComVariant vtZero(0);
			pColl->item(vtZero,vtZero,&pChildDispatch);
			CComQIPtr<IHTMLElement> pChildElement = pChildDispatch;
			if(pChildElement)
			{
				CXFormsParseContextualValue oParser(true);
				CImplContextualValue * pNameResolver = new CImplContextualValue();
				if(SUCCEEDED(oParser.parse(pNameResolver,pChildElement)))
				{
					pColl.Release();
					pChildDispatch.Release();
					pChildElement.Release();

					pEl2->getElementsByTagName(L"value",&pColl);
					pColl->get_length(&l);
					if(l> 0)
					{
						CComPtr<IDispatch> pChildDispatch;
						CComVariant vtZero(0);
						pColl->item(vtZero,vtZero,&pChildDispatch);
						CComQIPtr<IHTMLElement> pChildElement = pChildDispatch;
						if(pChildElement)
						{
							CImplContextualValue * pValueResolver = new CImplContextualValue();
							if(SUCCEEDED(oParser.parse(pValueResolver,pChildElement)))
							{
								CImplHeader * pHeader = new CImplHeader(pNameResolver,pValueResolver);

								CComVariant vtTemp;
								pElem->getAttribute(L"nodeset",1,&vtTemp);
								if(vtTemp.vt == VT_BSTR)
									vtTemp.CopyTo(&pHeader->m_sNodeset);
								CImplSubmitInfo * pSubmitInfo = dynamic_cast<CImplSubmitInfo*>(pImpl);
								pSubmitInfo->AddHeaderObject(pHeader);
							}
							else
							{
								delete pValueResolver;
							}

						}
						else
						{
							delete pNameResolver;
						}
					}
				}
				else
				{
					delete pNameResolver;
				}
			}

		}




/*		CComVariant vtTemp;
		pElem->getAttribute(L"name",1,&vtTemp);
		CComBSTR sHeaderName;
		vtTemp.CopyTo(&sHeaderName);
		if(!sHeaderName)
		{
			//ignore
		}
		else
		{
			CImplSubmitInfo * pSubmitInfo = dynamic_cast<CImplSubmitInfo*>(pImpl);
			if(pSubmitInfo)
			{
				pElem->getAttribute(L"value",1,&vtTemp);
				CComBSTR sValue;
				if(vtTemp.vt == VT_NULL)
				{
					//in this case, it is a plain text value
					pElem->get_innerText(&sValue);
					pSubmitInfo->AddHeader(sHeaderName,sValue);
				}	
				else
				{
					vtTemp.CopyTo(&sValue);
					//@value indicates a value expression to be evaluated.
					pSubmitInfo->AddHeaderExpression(sHeaderName,sValue);
				}
			}
		}
		*/
	}	
}
